package web_mapper

import (
	"context"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"sync"
	"transport/web/web_model"
)

type OrderrMapper struct {
	DB   *gorm.DB
	Ctx  context.Context
	Lock *sync.RWMutex
}

func (mapper *OrderrMapper) Create(m *web_model.TransOrder) (ret *web_model.TransOrder, err error) {
	mapper.Lock.Lock()
	defer mapper.Lock.Unlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Create(m).Error; err != nil {
		return nil, err
	}
	return m, nil
}
func (mapper *OrderrMapper) Upsert(m *web_model.TransOrder) (ret *web_model.TransOrder, err error) {
	if err = mapper.DB.WithContext(mapper.Ctx).Clauses(clause.OnConflict{
		Columns:   []clause.Column{{Name: "order_code"}},
		DoUpdates: clause.AssignmentColumns([]string{"customer_code", "customer_name", "route", "priority_level", "pack_count"}),
	}).Create(m).Error; err != nil {
		return nil, err
	}
	return m, nil
}
func (mapper *OrderrMapper) Update(m *web_model.TransOrder) (ret *web_model.TransOrder, err error) {
	mapper.Lock.Lock()
	defer mapper.Lock.Unlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Model(&web_model.TransOrder{}).Where("id = ?", m.ID).Updates(m).Error; err != nil {
		return nil, err
	}
	return m, nil
}
func (mapper *OrderrMapper) UpdateStatus(orderCode, status string) (err error) {
	mapper.Lock.Lock()
	defer mapper.Lock.Unlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Model(&web_model.TransOrder{}).Where("order_code = ?", orderCode).Update("status", status).Error; err != nil {
		return err
	}
	return nil
}
func (mapper *OrderrMapper) UpdateBillInfo(orderId, billId int64, billSn string) (err error) {
	mapper.Lock.Lock()
	defer mapper.Lock.Unlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Model(&web_model.TransOrder{}).Where("id = ?", orderId).
		Updates(map[string]interface{}{"trans_bill_id": billId, "trans_bill_sn": billSn}).Error; err != nil {
		return err
	}
	return nil
}
func (mapper *OrderrMapper) UpdateOrderToUnbind(billId int64) (err error) {
	mapper.Lock.Lock()
	defer mapper.Lock.Unlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Model(&web_model.TransOrder{}).Where("trans_bill_id = ?", billId).
		Updates(map[string]interface{}{"trans_bill_id": 0, "trans_bill_sn": ""}).Error; err != nil {
		return err
	}
	return nil
}
func (mapper *OrderrMapper) UpdateRouteByCustomerCode(routeName, customerCode string) (err error) {
	mapper.Lock.Lock()
	defer mapper.Lock.Unlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Model(&web_model.TransOrder{}).Where("customer_code = ? and route != ?", customerCode, routeName).
		Updates(map[string]interface{}{"route": routeName}).Error; err != nil {
		return err
	}
	return nil
}
func (mapper *OrderrMapper) UpdateOrderTempType() (err error) {
	mapper.Lock.Lock()
	defer mapper.Lock.Unlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Table("trans_order").Where("trans_temp_type IS NULL or trans_temp_type = ''").
		Update("trans_temp_type", mapper.DB.WithContext(mapper.Ctx).Raw("SELECT storage_type FROM trans_order_detail tod where trans_order.order_code = tod.order_code  LIMIT 1")).Error; err != nil {
		return err
	}
	return nil
}
func (mapper *OrderrMapper) UpdateOrderRoute() (err error) {
	mapper.Lock.Lock()
	defer mapper.Lock.Unlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Table("trans_order").Where("route IS NULL or route = ''").
		Update("route", mapper.DB.WithContext(mapper.Ctx).Raw("SELECT trans_merchants.route_name FROM trans_merchants WHERE trans_merchants.code = trans_order.customer_code LIMIT 1")).Error; err != nil {
		return err
	}
	return nil
}
func (mapper *OrderrMapper) CreateOrUpdate(m *web_model.TransOrder) (ret *web_model.TransOrder, err error) {
	mapper.Lock.Lock()
	defer mapper.Lock.Unlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Model(m).Save(m).Error; err != nil {
		return nil, err
	}
	return m, nil
}

func (mapper *OrderrMapper) QueryById(id int64) (m *web_model.TransOrder, err error) {
	mapper.Lock.RLock()
	defer mapper.Lock.RUnlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Model(&web_model.TransOrder{}).Where("id = ?", id).First(&m).Error; err != nil {
		return nil, err
	}
	return m, nil
}

func (mapper *OrderrMapper) QueryNotBind() (m []*web_model.TransOrder, err error) {
	mapper.Lock.RLock()
	defer mapper.Lock.RUnlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Model(&web_model.TransOrder{}).Where("trans_bill_sn IS NULL OR trans_bill_sn = ''").Find(&m).Error; err != nil {
		return nil, err
	}
	return m, nil
}

func (mapper *OrderrMapper) QueryByIds(ids []int64) (m []*web_model.TransOrder, err error) {
	mapper.Lock.RLock()
	defer mapper.Lock.RUnlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Model(&web_model.TransOrder{}).Where("id IN ?", ids).Find(&m).Error; err != nil {
		return nil, err
	}
	return m, nil
}
func (mapper *OrderrMapper) DeleteById(id int64) (err error) {
	mapper.Lock.Lock()
	defer mapper.Lock.Unlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Unscoped().Where("id = ?", id).Delete(&web_model.TransOrder{}).Error; err != nil {
		return err
	}
	return nil
}

func (mapper *OrderrMapper) DeleteByIds(ids []int64) (err error) {
	mapper.Lock.Lock()
	defer mapper.Lock.Unlock()
	if err := mapper.DB.WithContext(mapper.Ctx).Unscoped().Where("id IN ?", ids).Delete(&web_model.TransOrder{}).Error; err != nil {
		return err
	}
	return nil
}

func (mapper *OrderrMapper) Page(pageIndex, pageSize int, orderCode, billSn, customerName, routeName, priorityLevel, status, tempType string) (items []*web_model.TransOrder, count int64, err error) {
	mapper.Lock.RLock()
	defer mapper.Lock.RUnlock()
	var countTmp int64 = 0
	table := mapper.DB.WithContext(mapper.Ctx)
	if orderCode != "" {
		table = table.Where("order_code like ?", "%"+orderCode+"%")
	}
	if billSn != "" {
		table = table.Where("trans_bill_sn like ?", "%"+billSn+"%")
	}
	if customerName != "" {
		table = table.Where("customer_name like ?", "%"+customerName+"%")
	}
	if routeName != "" {
		table = table.Where("route like ?", "%"+routeName+"%")
	}
	if priorityLevel != "" {
		table = table.Where("priority_level = ?", priorityLevel)
	}
	if status != "" {
		table = table.Where("status = ?", status)
	}
	if tempType != "" {
		table = table.Where("trans_temp_type = ?", tempType)
	}
	if err := table.Order("sort").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&items).Offset(-1).Limit(-1).Count(&countTmp).Error; err != nil {
		return nil, 0, err
	}
	return items, countTmp, nil
}
func (mapper *OrderrMapper) PageNotBind(pageIndex, pageSize int, orderCode, billSn, customerName, routeName, priorityLevel, status, tempType string) (items []*web_model.TransOrder, count int64, err error) {
	mapper.Lock.RLock()
	defer mapper.Lock.RUnlock()
	var countTmp int64 = 0
	table := mapper.DB.WithContext(mapper.Ctx)
	if orderCode != "" {
		table = table.Where("order_code like ?", "%"+orderCode+"%")
	}
	if billSn != "" {
		table = table.Where("trans_bill_sn like ?", "%"+billSn+"%")
	}
	if customerName != "" {
		table = table.Where("customer_name like ?", "%"+customerName+"%")
	}
	if routeName != "" {
		table = table.Where("route like ?", "%"+routeName+"%")
	}
	if priorityLevel != "" {
		table = table.Where("priority_level = ?", priorityLevel)
	}
	if status != "" {
		table = table.Where("status = ?", status)
	}
	if tempType != "" {
		table = table.Where("trans_temp_type = ?", tempType)
	}
	table = table.Where("trans_bill_id = 0 OR trans_bill_id IS NULL")
	if err := table.Order("sort").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&items).Offset(-1).Limit(-1).Count(&countTmp).Error; err != nil {
		return nil, 0, err
	}
	return items, countTmp, nil
}
func (mapper *OrderrMapper) PageApp(pageIndex, pageSize int, billSn string) (items []*web_model.TransOrder, count int64, err error) {
	mapper.Lock.RLock()
	defer mapper.Lock.RUnlock()
	var countTmp int64 = 0
	table := mapper.DB.WithContext(mapper.Ctx)
	if billSn != "" {
		table = table.Where("trans_bill_sn like ?", "%"+billSn+"%")
	}
	if err := table.Order("sort,customer_name").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&items).Offset(-1).Limit(-1).Count(&countTmp).Error; err != nil {
		return nil, 0, err
	}
	return items, countTmp, nil
}
func (mapper *OrderrMapper) List(billSn, status string) (items []*web_model.TransOrder, count int64, err error) {
	mapper.Lock.RLock()
	defer mapper.Lock.RUnlock()
	var countTmp int64 = 0
	table := mapper.DB.WithContext(mapper.Ctx)
	if billSn != "" {
		table = table.Where("trans_bill_sn = ?", billSn)
	}
	if status != "" {
		table = table.Where("status = ?", status)
	}
	if err := table.Find(&items).Offset(-1).Limit(-1).Count(&countTmp).Error; err != nil {
		return nil, 0, err
	}
	return items, countTmp, nil
}
func (mapper *OrderrMapper) ListApp(billSn string) (items []*web_model.TransOrder, count int64, err error) {
	mapper.Lock.RLock()
	defer mapper.Lock.RUnlock()
	var countTmp int64 = 0
	table := mapper.DB.WithContext(mapper.Ctx)
	if billSn != "" {
		table = table.Where("trans_bill_sn = ?", billSn)
	}
	if err := table.Find(&items).Offset(-1).Limit(-1).Count(&countTmp).Error; err != nil {
		return nil, 0, err
	}
	return items, countTmp, nil
}
